;
(function(win) {

	var JadeEngine = {};

	JadeEngine.version = "1.0.0.RELEASE";

	JadeEngine.author = "yumi@omuao.com";

	win.JadeEngine = JadeEngine;

	JadeEngine.renderEngineType = "default";

	JadeEngine.renderEngineMap = {};

	JadeEngine.openWarnLog = true;

	JadeEngine.openInfoLog = true;

	JadeEngine.openErrorLog = true;

	JadeEngine.renderEngineRegister = function(key, render) {
		JadeEngine.renderEngineMap[key] = render;
	}

	JadeEngine.renderEngineRegister("default", function(data) {
		//		console.log(JSON.stringify(data));
	});

	JadeEngine.clock = function() {
		var timestamp = new Date().getTime();
		return timestamp;
	}

	JadeEngine.getDate = function() {
		return new Date(JadeEngine.clock()).getDate();
	}

	JadeEngine.getHours = function() {
		return new Date(JadeEngine.clock()).getHours();
	}

	JadeEngine.getMinutes = function() {
		return new Date(JadeEngine.clock()).getMinutes();
	}

	JadeEngine.getSeconds = function() {
		return new Date(JadeEngine.clock()).getSeconds();
	}

	JadeEngine.getMonth = function() {
		var date = new Date(JadeEngine.clock());
		return (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
	}

	JadeEngine.getFullYear = function() {
		return new Date(JadeEngine.clock()).getFullYear();
	}

	JadeEngine.weightRondom = function(obj, num) {
		var indexObject = [];
		for (var key in obj) {
			var max = obj[key] * num;
			for (var i = 0; i < max; i++) {
				var weightObject = {};
				weightObject.key = key;
				indexObject.push(weightObject);
			}
		}
		var index = Math.floor(Math.random() * indexObject.length);
		var keyIndex = indexObject[index].key;
		return keyIndex;
	}

	//晴、阴、大雨、小雨、阵雨、多云、冰雹、雷阵雨
	JadeEngine.weatherArray = ["Sunny", "Overcast", "HeavyRain", "LightRain", "Shower", "Cloudy", "Hail", "Thunderstorm"];

	//风等级 1-17
	JadeEngine.windLevelArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17];

	//地震等级
	JadeEngine.earthquakeLevelArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

	//其他自然灾害等级
	JadeEngine.otherNaturalDisasterLevelArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

	//其他自然灾害名称 虫害、旱灾、洪涝、陨石撞击、火山喷发
	JadeEngine.otherNaturalDisasterNameArray = ["Pests", "Drought", "Flood", "Meteorite", "Volcano", "None"];

	//天气
	JadeEngine.weather = {};

	//天气权重
	JadeEngine.weather.weight = {
		"Sunny": 4,
		"Overcast": 4,
		"HeavyRain": 3,
		"LightRain": 4,
		"Shower": 3,
		"Cloudy": 4,
		"Hail": 2,
		"Thunderstorm": 1
	}

	JadeEngine.weather.next = function() {
		return JadeEngine.weightRondom(JadeEngine.weather.weight, 10);
	}

	JadeEngine.wind = {};

	//风等级权重
	JadeEngine.wind.weight = {
		"0": 180,
		"1": 170,
		"2": 160,
		"3": 150,
		"4": 140,
		"5": 13,
		"6": 12,
		"7": 11,
		"8": 10,
		"9": 9,
		"10": 8,
		"11": 7,
		"12": 6,
		"13": 5,
		"14": 4,
		"15": 3,
		"16": 2,
		"17": 1
	}

	JadeEngine.wind.next = function() {
		return JadeEngine.weightRondom(JadeEngine.wind.weight, 10);
	}

	JadeEngine.earthquake = {};

	//地震权重
	JadeEngine.earthquake.weight = {
		"0": 800,
		"1": 10,
		"2": 9,
		"3": 8,
		"4": 7,
		"5": 6,
		"6": 5,
		"7": 4,
		"8": 3,
		"9": 2,
		"10": 1
	}

	JadeEngine.earthquake.next = function() {
		return JadeEngine.weightRondom(JadeEngine.earthquake.weight, 10);
	}

	JadeEngine.otherNaturalDisasterLevel = {};

	//其他自然灾害权重
	JadeEngine.otherNaturalDisasterLevel.weight = {
		"1": 10,
		"2": 9,
		"3": 8,
		"4": 7,
		"5": 6,
		"6": 5,
		"7": 4,
		"8": 3,
		"9": 2,
		"10": 1
	}

	JadeEngine.otherNaturalDisasterLevel.next = function() {
		return JadeEngine.weightRondom(JadeEngine.otherNaturalDisasterLevel.weight, 10);
	}

	JadeEngine.otherNaturalDisasterName = {};

	//其他自然灾害权重
	JadeEngine.otherNaturalDisasterName.weight = {
		"None": 800,
		"Pests": 3,
		"Drought": 3,
		"Flood": 3,
		"Meteorite": 1,
		"Volcano": 2
	}

	JadeEngine.otherNaturalDisasterName.next = function() {
		return JadeEngine.weightRondom(JadeEngine.otherNaturalDisasterName.weight, 10);
	}

	/**
	 * 定时器组件
	 * @param {Object} option 参数
	 */
	win.JadeTimer = function(option) {
		//计数器
		var counter = 0;

		//执行任务的ID
		var taskId = null;

		//时间单位量。1000ms = 1秒
		var unit = 1000;

		//任务函数
		var task = null;

		//Timer名称
		var name = "default";

		/**
		 * 启动
		 */
		this.start = function start() {
			var that = this; // 保存当前对象this
			counter++;
			taskId = setTimeout(function() {
				that.stop();
				that.start();
			}, unit);
			if (task != null && typeof task === "function") {
				task(counter);
			}
			return this;
		};

		/**
		 * 完全终止
		 */
		this.stop = function(callback) {
			if (taskId != null && taskId != undefined) {
				counter = 0;
				clearTimeout(taskId);
			}
			if (callback != null && typeof task === "function") {
				callback();
			}
			return this;
		};

		/**
		 * 暂停终止
		 */
		this.suspend = function(callback) {
			if (taskId != null && taskId != undefined) {
				clearTimeout(taskId);
			}
			if (callback != null && typeof task === "function") {
				callback();
			}
			return this;
		};

		/**
		 * 获得Timer名称
		 */
		this.getName = function() {
			return name;
		};

		this.setName = function(_name) {
			if (typeof _name !== 'string') {
				throw "仅支持String 类型的参数！"
			}
			name = _name;
			return this;
		};

		this.setUnit = function(_unit) {
			if (typeof _unit !== 'number') {
				throw "仅支持Number 类型的参数！"
			}
			unit = _unit;
			return this;
		};

		this.getUnit = function() {
			return unit;
		};

		/**
		 * 设置任务
		 */
		this.setTask = function(_task) {
			if (typeof _task !== 'function') {
				throw "仅支持Funtion 类型的参数！"
			}
			task = _task;
			return this;
		};

		/**
		 * 获得当前任务
		 */
		this.getTask = function() {
			return task;
		};

		/**
		 * 获得计数器
		 */
		this.getCounter = function() {
			return counter;
		};

		if (option != null && typeof option !== "undefined") {
			this.setTask(option.task);
			this.setName(option.name);
			this.setUnit(option.unit);
		}

	};

	//天气
	JadeEngine.event = {};
	//事件
	JadeEngine.event.pool = {};

	JadeEngine.event.trigger = {};

	JadeEngine.event.toArray = function() {
		var array = [];
		for (var key in JadeEngine.event.pool) {
			array.push(JadeEngine.event.pool[key]);
		}
		return array;
	}

	JadeEngine.event.triggerWeather = function(weather, date) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "weather";
		params.weather = weather;
		params.date = date;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	JadeEngine.event.triggerWind = function(wind, date) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "wind";
		params.wind = wind;
		params.date = date;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	JadeEngine.event.triggerEarthquake = function(earthquake, date) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "earthquake";
		params.earthquake = earthquake;
		params.date = date;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	JadeEngine.event.triggerOtherNatural = function(otherNaturalName, otherNaturalLevel, date) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "otherNatural";
		params.otherNaturalName = otherNaturalName;
		params.otherNaturalLevel = otherNaturalLevel;
		params.date = date;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	JadeEngine.event.triggerSesson = function(sesson) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "sesson";
		params.sesson = sesson;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	JadeEngine.event.triggerYear = function(year) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "year";
		params.year = year;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	JadeEngine.event.triggerMonth = function(month) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "month";
		params.month = month;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	JadeEngine.event.triggerWeek = function(week) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "week";
		params.week = week;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	JadeEngine.event.triggerDate = function(date) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "date";
		params.date = date;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	JadeEngine.event.triggerHour = function(hour) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "hour";
		params.hour = hour;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	JadeEngine.event.triggerMinute = function(minute) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "minute";
		params.minute = minute;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	JadeEngine.event.triggerSecond = function(second) {
		if (win.jadeSystem == null || typeof win.jadeSystem === "undefined") {
			return;
		}
		var arrays = JadeEngine.event.toArray();
		var params = {};
		params.eventType = "second";
		params.second = second;
		jadeSystem.notifyArrayAndResult(arrays, "onEvent", params)
	}

	/**
	 * 虚拟时钟值
	 */
	JadeEngine.system = {};

	JadeEngine.system.weather = {};
	JadeEngine.system.weather.isDefault = true;
	JadeEngine.system.wind = {};
	JadeEngine.system.wind.isDefault = true;
	JadeEngine.system.earthquake = {};
	JadeEngine.system.earthquake.isDefault = true;
	JadeEngine.system.otherNatural = {};
	JadeEngine.system.otherNatural.isDefault = true;

	JadeEngine.system.event = {};

	JadeEngine.system.event.clock = {};

	JadeEngine.system.event.lisenters = {};

	JadeEngine.system.event.addLisenter = function(name, callback) {
		var lisenters = JadeEngine.system.event.lisenters;
		lisenters[name] = callback;
	}

	/**
	 * 引擎系统时钟
	 */
	JadeEngine.system.clock = 10000;

	//当前年
	JadeEngine.system.year = 1;

	//当前月
	JadeEngine.system.month = 1;

	//当前季节
	JadeEngine.system.season = "winter";

	/**
	 * 判断闰年
	 * @param {Object} year
	 */
	JadeEngine.system.isLeapYear = function(year) {
		if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
			return true;
		}
		return false;
	}

	JadeEngine.system.isMonth29 = function(year, month) {
		if (JadeEngine.system.isLeapYear(year) && month == 2) {
			return true;
		}
		return false;
	}

	JadeEngine.system.isMonth31 = function(month) {
		var month31 = [1, 3, 5, 7, 8, 10, 12];
		for (var i = 0; i < month31.length; i++) {
			if (month31[i] == month) {
				return true;
			}
		}
		return false;
	}

	JadeEngine.system.seasonByMonth = function(month) {

		if (JadeEngine.system.isSpring(month)) {
			return "spring";
		}

		if (JadeEngine.system.isSummer(month)) {
			return "summer";
		}

		if (JadeEngine.system.isAutumn(month)) {
			return "autumn";
		}

		return "winter";
	}

	JadeEngine.system.isSpring = function(month) {
		var season = [3, 4, 5];
		for (var i = 0; i < season.length; i++) {
			if (season[i] == month) {
				return true;
			}
		}
		return false;
	}

	JadeEngine.system.isSummer = function(month) {
		var season = [6, 7, 8];
		for (var i = 0; i < season.length; i++) {
			if (season[i] == month) {
				return true;
			}
		}
		return false;
	}

	JadeEngine.system.isAutumn = function(month) {
		var season = [9, 10, 11];
		for (var i = 0; i < season.length; i++) {
			if (season[i] == month) {
				return true;
			}
		}
		return false;
	}

	JadeEngine.system.isWinter = function(month) {
		var season = [12, 1, 2];
		for (var i = 0; i < season.length; i++) {
			if (season[i] == month) {
				return true;
			}
		}
		return false;
	}

	JadeEngine.system.timer = new JadeTimer();

	JadeEngine.system.timer.setUnit(1);

	JadeEngine.system.weather.defaultLisenter = function(date) {

		var lisenters = JadeEngine.system.event.lisenters;

		var onWeatherChange = lisenters.onWeatherChange;

		if (JadeEngine.system.weather.isDefault) {
			var weather = JadeEngine.weather.next();
			//天气
			if (onWeatherChange != null && typeof onWeatherChange === "function") {
				onWeatherChange(weather, date);
			}
			JadeEngine.event.triggerWeather(weather, date);
		}

		var onWindChange = lisenters.onWindChange;

		if (JadeEngine.system.wind.isDefault) {
			var wind = JadeEngine.wind.next();

			//飓风
			if (onWindChange != null && typeof onWindChange === "function") {

				onWindChange(JadeEngine.wind.next(), date);
			}
			JadeEngine.event.triggerWind(wind, date);
		}
		var onEarthquakeChange = lisenters.onEarthquakeChange;

		if (JadeEngine.system.earthquake.isDefault) {
			var earthquake = JadeEngine.earthquake.next();

			//地震
			if (onEarthquakeChange != null && typeof onEarthquakeChange === "function") {

				onEarthquakeChange(earthquake, date);
			}
			JadeEngine.event.triggerEarthquake(earthquake, date);
		}

		var onOtherNaturalChange = lisenters.onOtherNaturalChange;

		if (JadeEngine.system.otherNatural.isDefault) {

			var name = JadeEngine.otherNaturalDisasterName.next();

			var level = JadeEngine.otherNaturalDisasterLevel.next();

			//其他自然灾害
			if (onOtherNaturalChange != null && typeof onOtherNaturalChange === "function") {

				onOtherNaturalChange(name, level, date);
			}
			JadeEngine.event.triggerOtherNatural(name, level, date);
		}
	}

	JadeEngine.system.clockLisenter = function(clock) {

		var lisenters = JadeEngine.system.event.lisenters;

		var onSecondChange = lisenters.onSecondChange;

		//秒
		if (onSecondChange != null && typeof onSecondChange === "function") {
			onSecondChange(clock % 60);
		}
		JadeEngine.event.triggerSecond(clock % 60);

		//分钟
		var onMinuteChange = lisenters.onMinuteChange;

		if (clock % 60 == 0) {
			if (onMinuteChange != null && typeof onMinuteChange === "function") {
				onMinuteChange(clock / 60 % 60);
			}
			JadeEngine.event.triggerMinute(clock / 60 % 60);
		}

		//小时
		var onHourChange = lisenters.onHourChange;
		if (clock % 3600 == 0) {
			if (onHourChange != null && typeof onHourChange === "function") {
				onHourChange(clock / 3600 % 24);
			}
			JadeEngine.event.triggerHour(clock / 3600 % 24);
		}

		//天
		var onDateChange = lisenters.onDateChange;
		if (clock % (24 * 3600) == 0) {
			if (onDateChange != null && typeof onDateChange === "function") {
				onDateChange(clock % (24 * 3600));
			}
			JadeEngine.event.triggerDate(clock % (24 * 3600));
			JadeEngine.system.weather.defaultLisenter(clock % (24 * 3600));
		}

		//周
		var onWeekChange = lisenters.onWeekChange;
		if (clock % (7 * 24 * 3600) == 0) {
			if (onWeekChange != null && typeof onWeekChange === "function") {
				onWeekChange(clock % (7 * 24 * 3600));
			}
			JadeEngine.event.triggerWeek(clock % (7 * 24 * 3600));
		}

		//月
		var onMonthChange = lisenters.onMonthChange;

		var month = JadeEngine.system.month;
		var year = JadeEngine.system.year;

		if (JadeEngine.system.isMonth31(month)) {
			if (clock % (31 * 24 * 3600) == 0) {
				JadeEngine.system.month = JadeEngine.system.month + 1;
				if (onMonthChange != null && typeof onMonthChange === "function") {
					onMonthChange(JadeEngine.system.month);
				}
				JadeEngine.event.triggerMonth(JadeEngine.system.month);
			}
		} else {
			if (JadeEngine.system.isMonth29(month)) {
				if (clock % (29 * 24 * 3600) == 0) {
					JadeEngine.system.month = JadeEngine.system.month + 1;
					if (onMonthChange != null && typeof onMonthChange === "function") {
						onMonthChange(JadeEngine.system.month);
					}
					JadeEngine.event.triggerMonth(JadeEngine.system.month);
				}
			} else {
				if (clock % (30 * 24 * 3600) == 0) {
					JadeEngine.system.month = JadeEngine.system.month + 1;
					if (onMonthChange != null && typeof onMonthChange === "function") {
						onMonthChange(JadeEngine.system.month);
					}
					JadeEngine.event.triggerMonth(JadeEngine.system.month);
				}
			}
		}

		//年
		var onYearChange = lisenters.onYearChange;

		if (JadeEngine.system.isLeapYear(year)) {
			if (clock % (366 * 24 * 3600) == 0) {
				JadeEngine.system.year = JadeEngine.system.year + 1;
				if (onYearChange != null && typeof onYearChange === "function") {
					onYearChange(JadeEngine.system.year);
				}
				JadeEngine.event.triggerYear(JadeEngine.system.year);
			}
		} else {
			if (clock % (365 * 24 * 3600) == 0) {
				JadeEngine.system.year = JadeEngine.system.year + 1;
				if (onYearChange != null && typeof onYearChange === "function") {
					onYearChange(JadeEngine.system.year);
				}
				JadeEngine.event.triggerYear(JadeEngine.system.year);
			}
		}

		//季节
		var season = JadeEngine.system.seasonByMonth(JadeEngine.system.month);

		//月
		var onSeasonChange = lisenters.onSeasonChange;

		if (season != JadeEngine.system.season) {
			JadeEngine.system.season = season;
			if (onSeasonChange != null && typeof onSeasonChange === "function") {
				onSeasonChange(JadeEngine.system.season);
			}
			JadeEngine.event.triggerSesson(JadeEngine.system.season);
		}
	}

	JadeEngine.system.timer.setTask(function(counter) {
		JadeEngine.system.clock = JadeEngine.system.clock + 1;
		JadeEngine.system.clockLisenter(JadeEngine.system.clock);
	});

}(window));
